using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Forms;
using iTunesExport.Parser;
using System.IO;


namespace iTunesUtil
{   
    public sealed partial class MainForm : Form
    {        
        private readonly TreeNode treeNodeRoot;        
        static private LibraryParser lp;

        static TreeNode AddCollection(TrackCollection tc, TreeNode dad)
        {            
            TreeNode tnCollection = dad.Nodes.Add(tc.Name);
            tnCollection.Tag = tc;
            foreach (Track t in tc.Tracks)
            {
                tnCollection.Nodes.Add(t.ToString()).Tag = t;
            }
            return tnCollection;
        }         
        void AddCollections(IEnumerable<TrackCollection> tcs, string name)
        {            
            TreeNode tn = treeView1.Nodes.Add(name);
            var sb = new StringBuilder();
            sb.AppendLine(name);
            foreach (var tc in tcs)
            {
                sb.AppendLine(string.Format("{0:d4} items in  with {1} ", tc.Count, tc.Name));
                AddCollection(tc, tn);
            }
            tn.Tag = sb.ToString();
        }        

        public MainForm()
        {
            InitializeComponent();
            Cursor = Cursors.WaitCursor;
            Refresh();
            lp = new LibraryParser(LibraryParser.GetDefaultLibraryLocation());
            treeNodeRoot = treeView1.Nodes.Add("iTunes");
            AddCollections(lp.Genres, "Genre");
            AddCollections(lp.Playlists2, "Playlist");
            AddCollections(lp.Artists, "Artists");                                                         
            Cursor = Cursors.Default;
        }
        
        #region Main Event Handler                     
        private void OnExportAllTracks(object sender, EventArgs e)
        {
            TrackCollection[] allTracks = { lp.AllTracks };            
            new ExportDlg(allTracks, "All Tracks").ShowDialog();            
        } 
        private void OnExportPlaylist(object sender, EventArgs e)
        {
            new ExportDlg(lp.Playlists2, "Playlists").ShowDialog();            
        }
        private void OnExportArtist(object sender, EventArgs e)
        {
            new ExportDlg(lp.Artists, "Artists").ShowDialog();            
        } 
        private void OnExportGenre(object sender, EventArgs e)
        {
            new ExportDlg(lp.Genres, "Genres").ShowDialog();            
        }
        private void OnCheckITunes(object sender, EventArgs e)
        {
            var dlg = new CheckITunesFiles(lp.AllTracks);            
            dlg.ShowDialog();            
            var tn = AddCollection(dlg.MissingTracks, treeNodeRoot);
            tn.Nodes.Add("Info").Tag = dlg.Info;
        }        
        private void OnCheckDir(object sender, EventArgs e)
        {
            var dlg = new CheckDlg(lp.AllTracks);
            if (dlg.ShowDialog() != DialogResult.OK)
                return;
            
            string msg;
            if (dlg.NoCheckedFiles == dlg.NoFilesInDir)
            {
                msg = string.Format("All {0} files from '{1}' checked, {2} files are missing.",
                    dlg.NoFilesInDir, dlg.Dir, dlg.MissingFiles.Count);
                MessageBox.Show(msg, Text, MessageBoxButtons.OK, MessageBoxIcon.Information);
            }
            else
            {
                msg = string.Format(" {0}/{1} files from '{2}' checked, {3} files are missing.",
                    dlg.NoCheckedFiles, dlg.NoFilesInDir, dlg.Dir, dlg.MissingFiles.Count);
                MessageBox.Show(msg, Text, MessageBoxButtons.OK, MessageBoxIcon.Warning);
            }

            TreeNode tn = treeNodeRoot.Nodes.Add(string.Format("Checked '{0}' at {1}", dlg.Dir,DateTime.Now.ToShortTimeString()));
            tn.Tag = msg;
            foreach(string f in dlg.MissingFiles)
            {
                tn.Nodes.Add(f).Tag = Path.Combine(dlg.Dir, f);
            }
        }        
        
        private void OnAbout(object sender, EventArgs e)
        {
            new AboutBox().ShowDialog();
        }

        #endregion

        public static string CheckSimilars<T>(SimilarityCheck<T> sc, Converter<T, string> outConverter)
        {
            var sb = new StringBuilder();
            foreach(var kv in sc.Result)
            {
                if (kv.Value.Count < 2)
                    continue;
                sb.AppendLine(kv.Key);
                kv.Value.ForEach(v => sb.Append("....").AppendLine(outConverter(v)));
                sb.AppendLine(string.Empty);
            }
            return sb.ToString();
        }
        public static string CheckSimilarTrackNames()
        {            
            return CheckSimilars(new SimilarityCheck<Track>(lp.AllTracks.Tracks,t => t.Name), t => t.ToString());                
        }
        public static string CheckSimilarTracksByFileSize()
        {
            return CheckSimilars(new SimilarityCheck<Track>(lp.AllTracks.Tracks,t => new FileInfo(t.Location).Length.ToString()), t => t.ToString());
        }
        public static string CheckSimilarArtistNames()
        {
            return CheckSimilars(new SimilarityCheck<TrackCollection>(lp.Artists, tc => tc.Name), tc => tc.Name);                
        }               

        private void OnTreeViewMouseDoubleClick(object sender, MouseEventArgs e)
        {
            var sel = treeView1.SelectedNode;
            if (sel == null)
                return;

        
        }
        private void OnTreeViewAfterSelect(object sender, TreeViewEventArgs e)
        {            
            if (e.Node == null)
                return;

            richTextBoxOutput.Clear();
            if (e.Node.Tag is Track)
            {
                var t = (Track)e.Node.Tag;
                var sb = new StringBuilder();
                sb.Append("Genre: " ).AppendLine(t.Genre);
                sb.Append("Artist: " ).AppendLine(t.Artist);
                sb.Append("Album: " ).AppendLine(t.Album);
                sb.Append("Name: " ).AppendLine(t.Name);
                sb.Append("Location: " ).AppendLine(t.Location);
                sb.Append("Location Utf8: ").AppendLine(t.LocationUtf8);
                sb.Append("Id: " ).AppendLine(t.Id);
                sb.Append("FileName: " ).AppendLine(t.FileName);                
                sb.AppendLine(string.Format("Duration: {0} secs", t.TrackTime));
                richTextBoxOutput.Text = sb.ToString();
                return;
            }
            if (e.Node.Tag is TrackCollection)
            {
                var tc = (TrackCollection)e.Node.Tag;
                richTextBoxOutput.Text = tc.ToStringDetailed(true);
                return;
            }
            if (e.Node.Tag is string)
            {
                richTextBoxOutput.Text = (string)e.Node.Tag;
                return;
            }
        }
        private void optionsToolStripMenuItem_Click(object sender, EventArgs e)
        {
            new OptionsDlg().ShowDialog();
        }
       
        private void fileNamesToolStripMenuItem_Click_1(object sender, EventArgs e)
        {
            Cursor = Cursors.WaitCursor;
            var sb = new StringBuilder();
            var dict = new SortedDictionary<string, string>();
            foreach (var currTrack in lp.AllTracks.Tracks)
            {
                dict.Add(currTrack.Location, currTrack.LocationUtf8);
            }

            foreach(var item in dict)
            {
                sb.AppendLine(item.Value).Append("...UTF8 : ").AppendLine(item.Value).AppendLine(string.Empty);             
            }            
            treeNodeRoot.Nodes.Add(string.Format("{0} Files {1}", dict.Count, DateTime.Now.ToShortTimeString())).Tag = sb.ToString();
            Cursor = Cursors.Default;
        }    

        private void convertITunesLibraryFileToolStripMenuItem_Click(object sender, EventArgs e)
        {
            new FilterLibraryFile().ShowDialog();
        }
    }
}
